﻿/*
 * Copyright © 2020, Wuxi Safover Intelligent Technology Co., Ltd. All rights reserved.
 * 
 * 无锡安永智能科技有限公司版权所有，未经许可，不得用于商业用途
 * 
 * Visit: https://www.safover.com/ 
 */

using Safover.LidarCollector.Config;
using System;

namespace Safover.LidarCollector.Core
{
    public delegate void OperationFinishedEventHandler(object sender, RotaryTableOperationFinishedEventArgs e);

    public abstract class RotaryTableDevice : SerialPortDevice, IRotaryTable, IRotaryTableDeviceControllable
    {
        private BaseRotaryTableController CurrentController { get; set; }

        private BaseRotaryTableController ClosedStateController { get; }

        private BaseRotaryTableController OpenedStateController { get; }

        private BaseRotaryTableController WorkingStateController { get; }

        public float? VerticalAngle { get; protected set; }

        public float? HorizontalAngle { get; protected set; }

        public RotaryTableStatus Status => CurrentController.RotaryTableStatus;

        public bool CanOpen => CurrentController.CanOpen;

        public bool CanClose => CurrentController.CanClose;

        public bool CanOperate => CurrentController.CanOperate;

        public abstract bool MoveHorizontallyTo(float angle);

        public abstract bool MoveVerticallyTo(float angle);

        public abstract void StopMove();

        public abstract void QueryHorizontalAngle();

        public abstract void QueryVerticalAngle();

        public abstract bool RestoreZero();

        public RotaryTableDevice()
        {
            ClosedStateController = new RotaryTableClosedStateController(this);

            OpenedStateController = new RotaryTableOpenedStateController(this);

            WorkingStateController = new RotaryTableWorkingStateController(this);

            CurrentController = ClosedStateController;
        }

        protected override void ResetSerialPortParameters()
        {
            PortName = RuntimeConfigManager.Instance.RotaryTableConfig.PortName;
            BaudRate = RuntimeConfigManager.Instance.RotaryTableConfig.BaudRate;
        }

        internal void SetStatus(RotaryTableStatus status)
        {
            switch (status)
            {
                case RotaryTableStatus.Closed:
                    CurrentController = ClosedStateController;
                    break;
                case RotaryTableStatus.Opened:
                    CurrentController = OpenedStateController;
                    break;
                case RotaryTableStatus.Working:
                    CurrentController = WorkingStateController;
                    break;
                default:
                    throw new InvalidOperationException($"Illegal device status = [{status}].");
            }
        }

        bool IRotaryTableDeviceControllable.TryClose()
        {
            return CanClose && CurrentController.TryClose();
        }

        bool IRotaryTableDeviceControllable.TryMoveHorizontally(float angle)
        {
            return CanOperate && CurrentController.TryMoveHorizontally(angle);
        }

        //Task<bool> IRotaryTableDeviceControllable.TryMoveHorizontallyAsync(float angle, int timeout)
        //{
        //    return CanOperate ? CurrentController.TryMoveHorizontallyAsync(angle, timeout) : Task.FromResult(false);
        //}

        bool IRotaryTableDeviceControllable.TryMoveVertically(float angle)
        {
            return CanOperate && CurrentController.TryMoveVertically(angle);
        }

        //Task<bool> IRotaryTableDeviceControllable.TryMoveVerticallyAsync(float angle, int timeout)
        //{
        //    return CanOperate ? CurrentController.TryMoveVerticallyAsync(angle, timeout) : Task.FromResult(false);
        //}

        bool IRotaryTableDeviceControllable.TryRestoreZero()
        {
            return CanOperate && CurrentController.TryRestoreZero();
        }

        //Task<bool> IRotaryTableDeviceControllable.TryRestoreZeroAsync(int timeout)
        //{
        //    return CanOperate ? CurrentController.TryRestoreZeroAsync(timeout) : Task.FromResult(false);
        //}

        bool IRotaryTableDeviceControllable.TryOpen()
        {
            return CanOperate && CurrentController.TryOpen();
        }

    }
}
